import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.*
import cn.hutool.cache.impl.TimedCache
import cn.hutool.core.lang.UUID
import cn.hutool.core.swing.clipboard.ClipboardUtil
import cn.hutool.core.swing.clipboard.StrClipboardListener
import component.ClipboardEntity
import component.ComplexClipboardListener
import org.jetbrains.jewel.foundation.modifier.onHover
import org.jetbrains.jewel.foundation.theme.JewelTheme
import org.jetbrains.jewel.intui.standalone.theme.IntUiTheme
import org.jetbrains.jewel.intui.standalone.theme.darkThemeDefinition
import org.jetbrains.jewel.intui.window.decoratedWindow
import org.jetbrains.jewel.intui.window.styling.dark
import org.jetbrains.jewel.ui.ComponentStyling
import org.jetbrains.jewel.ui.component.Icon
import org.jetbrains.jewel.ui.component.Text
import org.jetbrains.jewel.ui.component.TextArea
import org.jetbrains.jewel.window.styling.TitleBarStyle
import org.jetbrains.skiko.toBitmap
import theme.SlackColors
import theme.slackBlack
import java.awt.Image
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.Transferable
import java.awt.image.BufferedImage

@OptIn(ExperimentalLayoutApi::class)
@Composable
@Preview
fun App() {

    val clipboardList = remember { mutableStateListOf<ClipboardEntity>() }

    // 剪贴板不设置收藏的情况下，默认存储保存时间是30分钟
    val timedCache: TimedCache<String, String> = TimedCache(60000 * 30)

    // 设置剪切板监听
    LaunchedEffect(Unit) {
        // 文字监听
        ClipboardUtil.listen(object: ComplexClipboardListener() {

            override fun onChange(clipboard: Clipboard, contents: String): Transferable? {
                println("clipboard text change ${contents}")
                val key = UUID.fastUUID().toString()
                clipboardList.add(0, ClipboardEntity(key).also {
                    it.text = contents
                    it.icon = "richtext/text.png"
                })
                timedCache.put(key, key)
                return null
            }

            // 图片监听
            override fun onChange(clipboard: Clipboard, contents: Image): Transferable? {
                val key = UUID.fastUUID().toString()
                clipboardList.add(0, ClipboardEntity(key).also {
                    it.image = contents
                    it.icon = "richtext/text.png"
                    it.type = "image"
                })
                println("clipboard image change")
                return null
            }

        }, false)

        // 定时删除
        timedCache.schedulePrune(1000)
        timedCache.setListener { key, cachedObject ->
            clipboardList.removeIf { it.key == key }
        }
    }

    FlowRow (
        modifier = Modifier.fillMaxWidth().fillMaxHeight()
            .animateContentSize(tween(1000))
            .background(color = slackBlack)
            .verticalScroll(rememberScrollState()),
        horizontalArrangement = Arrangement.Start
    ) {

        // 列表每隔3个数据，创建一个新的row
        val rowList = clipboardList.chunked(4)
        for (row in rowList) {
            row.forEach {
                Spacer(modifier = Modifier.width(10.dp))
                IconAndTextView(
                    icon = it.icon,
                    text = it.text,
                    image = it.image
                )
            }
            Spacer(modifier = Modifier.width(10.dp))
        }

    }

}

@OptIn(ExperimentalTextApi::class)
fun main() = application {

    val textStyle = TextStyle(fontFamily = FontFamily("Inter"))

    val themeDefinition = JewelTheme.darkThemeDefinition(defaultTextStyle = textStyle)

    IntUiTheme(
        themeDefinition,
        ComponentStyling.decoratedWindow(
            titleBarStyle = TitleBarStyle.dark()
        )
    ) {
        Window(onCloseRequest = ::exitApplication,
            state = WindowState(width = 600.dp, height = 400.dp, position = WindowPosition(Alignment.BottomEnd)),
            resizable = false,
            title = "番茄剪贴板",
            icon = painterResource("richtext/tomato.png"),
            alwaysOnTop = true
            ) {
            App()
        }
    }

}

@Composable
private fun IconAndTextView(
    modifier: Modifier = Modifier,
    icon: String,
    text: String?,
    image: Image?
) {
    val color = Color.White
    val backgroundColor = SlackColors.optionSelected
    val fadeInOutAnim = animateFloatAsState (
        targetValue = 0.5f,
        animationSpec = tween(durationMillis = 1000)
    )

    var collectBgImage by remember { mutableStateOf("richtext/collect.png") }
    var showMultiIcon by remember { mutableStateOf(false) }
    var chooseColor by remember { mutableStateOf(Color.White) }

    Column (
        modifier = modifier
            .width(132.dp)
            .height(140.dp)
            .padding(horizontal = 3.dp, vertical = 6.dp)
            .animateContentSize()
            .clip(shape = RoundedCornerShape(5.dp))
            .background(color = backgroundColor)
        ,
        verticalArrangement = Arrangement.SpaceBetween
    ) {

        Row(modifier = Modifier.fillMaxWidth()
            .padding(start = 6.dp, top = 6.dp, end = 6.dp, bottom = 2.dp)
            .height(100.dp)
        ) {
            Column {

                Row(modifier = Modifier.height(20.dp)) {
                    Box(modifier = Modifier.width(3.dp).height(16.dp).background(color = Color(66, 185, 131).copy(alpha = fadeInOutAnim.value)))

                    Spacer(modifier = Modifier.width(4.dp))

                    Icon(
                        painter = painterResource(icon),
                        contentDescription = null,
                        modifier = Modifier.size(16.dp),
                        tint = color
                    )
                    Spacer(
                        modifier = Modifier.width(6.dp)
                    )
                }

                Row(modifier = Modifier.height(80.dp)) {
                    if (text != null) {
                        TextArea(
                            value = text,
                            onValueChange = {},
                            modifier = Modifier.fillMaxHeight()
                        )
                    } else if (image != null) {
                        val bufferedImage = BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB)
                        val g2d = bufferedImage.createGraphics()
                        g2d.drawImage(image, 0, 0, null)
                        g2d.dispose()

                        Image(
                            bitmap = org.jetbrains.skia.Image.makeFromBitmap(bufferedImage.toBitmap()).toComposeImageBitmap(),
                            contentDescription = null,
                            modifier = Modifier.fillMaxSize()
                        )
                    }
                }

            }

        }

        Row(
            modifier = Modifier.fillMaxWidth()
                .height(26.dp)
                .padding(top = 3.dp, bottom = 3.dp),
            horizontalArrangement = Arrangement.End,
            verticalAlignment = Alignment.Bottom
        ) {

            Icon(
                painter = painterResource(collectBgImage),
                contentDescription = null,
                modifier = Modifier.size(16.dp).onHover {
                    collectBgImage = if (it) {
                        "richtext/collect_selected.png"
                    } else {
                        "richtext/collect.png"
                    }
                }
            )
            Spacer(modifier=Modifier.width(3.dp))

            Icon(
                painter = painterResource("richtext/copy.png"),
                contentDescription = null,
                modifier = Modifier.size(16.dp).onHover {
                    chooseColor = if (it) {
                        Color.LightGray
                    } else {
                        Color.White
                    }
                }.clickable {
                    ClipboardUtil.setStr(text)
                },
                tint = chooseColor
            )
        }

    }

}
